#include "st.h"
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h> 
#include <stddef.h>
#include <time.h>
#include <sys/time.h>

void get_cur_ms(uint64_t *milliseconds) {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    *milliseconds = (unsigned long long)(tv.tv_sec) * 1000 + (unsigned long long)(tv.tv_usec) / 1000;
}

typedef struct {
    bool val;
    bool last;
} EDGE_TRIG_t;

bool R_TRIG(EDGE_TRIG_t* inst) {
    bool is_r  = inst->val && !(inst->last);
    inst->last = inst->val;
    return is_r;
}

bool F_TRIG(EDGE_TRIG_t* inst) {
    bool is_f = !(inst->val) && inst->last;
    inst->last = inst->val;
    return is_f;
}

typedef struct {
    bool IN;
    uint64_t PT;
} TP_t;

void TP(TP_t* inst, bool* Q, uint64_t* ET) {
    static int STATE = 0;
    static bool PREV_IN = false;
    static uint64_t CURRENT_TIME, START_TIME;

    get_cur_ms(&CURRENT_TIME);

    if (STATE == 0 && !PREV_IN && inst->IN) {
        STATE = 1;
        *Q = true;
        get_cur_ms(&START_TIME);
    }
    else if (STATE == 1) {
        if (START_TIME + inst->PT <= CURRENT_TIME) {
            STATE = 2;
            *Q = false;
            *ET = inst->PT;
        }
        else {
            *ET = CURRENT_TIME - START_TIME;
        }
    }

    if (STATE == 2 && !inst->IN) {
        *ET = 0;
        STATE = 0;
    }

    PREV_IN = inst->IN;
}

typedef struct {
    bool IN;
    uint64_t PT;
    bool Q;
    uint64_t ET;
    int STATE;
    bool PREV_IN;
    uint64_t CURRENT_TIME;
    uint64_t START_TIME;
} TON;

void TON_Update(TON* ton) {
    get_cur_ms(&ton->CURRENT_TIME);//获取当前ms时间戳

    if (ton->STATE == 0 && !ton->PREV_IN && ton->IN) {
        ton->STATE = 1;
        ton->Q = false;
        ton->START_TIME = ton->CURRENT_TIME;
    }
    else if (ton->STATE == 1) {
        if (ton->START_TIME + ton->PT <= ton->CURRENT_TIME) {
            ton->STATE = 2;
            ton->Q = true;
            ton->ET = ton->PT;
        }
        else {
            ton->ET = ton->CURRENT_TIME - ton->START_TIME;
        }
    }

    if (ton->STATE == 2 && !ton->IN) {
        ton->ET = 0;
        ton->STATE = 0;
        ton->Q = false;
    }

    ton->PREV_IN = ton->IN;
}

typedef struct {
    bool IN;
    uint64_t PT;
    bool Q;
    uint64_t ET;
    int STATE;
    bool PREV_IN;
    uint64_t CURRENT_TIME;
    uint64_t START_TIME;
} TOF;

void TOF_Update(TOF* tof) {
    get_cur_ms(&tof->CURRENT_TIME);

    if (tof->STATE == 0 && tof->PREV_IN && !tof->IN) {
        tof->STATE = 1;
        tof->START_TIME = tof->CURRENT_TIME;
    }
    else if (tof->STATE == 1) {
        if (tof->START_TIME + tof->PT <= tof->CURRENT_TIME) {
            tof->STATE = 2;
            tof->ET = tof->PT;
        }
        else {
            tof->ET = tof->CURRENT_TIME - tof->START_TIME;
        }
    }

    if (tof->IN) {
        tof->ET = 0;
        tof->STATE = 0;
    }

    tof->Q = tof->IN || (tof->STATE == 1);
    tof->PREV_IN = tof->IN;
}

// 当停止信号来了之后 等个几秒之后再做一些动作
int tof_test() {
    TOF tof;
    tof.IN = false;
    tof.PT = 5000;  // 设置设定时间为 5 秒
    tof.Q = false;
    tof.ET = 0;
    tof.STATE = 0;
    tof.PREV_IN = false;
    tof.CURRENT_TIME = 0;
    tof.START_TIME = 0;

    // 模拟输入信号从低电平到高电平
    tof.IN = true;
    TOF_Update(&tof);
    printf("Input signal rising edge.\n");

    // 模拟输入信号保持高电平 2 秒
    sleep(2);

    // 模拟输入信号从高电平到低电平
    tof.IN = false;
    TOF_Update(&tof);
    printf("Input signal falling edge.\n");

    // 模拟输入信号保持低电平 3 秒
    // sleep(3);

    while(1){
        sleep(1);
        // 输出信号 Q 为真（TRUE）
        TOF_Update(&tof);
        if (tof.Q) {
            printf("Output signal Q is true.\n");
        }else{
            printf("Output signal Q is false.\n");
            break;
        }
    }


    return 0;
}

// 持续pt时间的IN为TRUE才执行将Q置为TRUE
int ton_test() {
    TON ton;
    ton.IN = false;
    ton.PT = 5000;  // 设置设定时间为 5 秒
    ton.Q = false;
    ton.ET = 0;
    ton.STATE = 0;
    ton.PREV_IN = false;
    ton.CURRENT_TIME = 0;
    ton.START_TIME = 0;

    // 车辆进入检测器检测到车辆进入
    ton.IN = true;
    TON_Update(&ton);

    printf("Vehicle entered.\n");

    while(1){
    // 车辆停留时间达到设定时间，触发警报
       sleep(1);
       printf("wait\n");
        TON_Update(&ton);
        if (ton.Q) {
            printf("Alarm triggered! Vehicle has been parked for %ld seconds.\n", ton.ET);
            break;
        }
    }
    sleep(1);
    ton.IN = false;
    TON_Update(&ton);
    ton.IN = false;
    TON_Update(&ton);

    printf("Vehicle left. %d, %ld\n", ton.Q, ton.ET);

    return 0;
}

// 用于给出一个持续PT秒的高电平脉冲信号,比如按键按下一瞬间弹起来，还能持续给输出TPs后结束
int tp_test() {
    TP_t signal;
    signal.IN = false;
    signal.PT = 5000;  // 设置计时时间为 5 秒

    bool Q = false;
    uint64_t ET = 0;

    signal.IN = false;
    TP(&signal, &Q, &ET);
    printf("Q: %d, ET: %ld\n", Q, ET);  // 输出: Q: 0, ET: 0

    signal.IN = true;
    TP(&signal, &Q, &ET);
    printf("Q: %d, ET: %ld\n", Q, ET);  // 输出: Q: 1, ET: 0

    while(Q){
        sleep(1);
        signal.IN = false;
        TP(&signal, &Q, &ET);
        printf("Q: %d, ET: %ld\n", Q, ET);  // 输出: Q: 1, ET: 0
    }
    return 0;
}

// 检测上升沿下降沿
int st_test() {
    EDGE_TRIG_t inst1 = {0};
    EDGE_TRIG_t inst2 = {0};

    inst1.val = true;
    bool Q = R_TRIG(&inst1);
    printf("Q: %d\n", Q);  // 输出: 1

    inst2.val = true;
    Q = R_TRIG(&inst2);
    printf("Q1: %d\n", Q);  // 输出: 1

    inst1.val = true;
    Q = R_TRIG(&inst1);
    printf("Q: %d\n", Q);  // 输出: 0

    inst2.val = true;
    Q = R_TRIG(&inst2);
    printf("Q1: %d\n", Q);  // 输出: 0

    inst1.val = false;
    Q = R_TRIG(&inst1);
    printf("Q: %d\n", Q);  // 输出: 0

    inst2.val = false;
    Q = R_TRIG(&inst2);
    printf("Q1: %d\n", Q);  // 输出: 0

    inst1.val = true;
    Q = F_TRIG(&inst1);
    printf("Q: %d\n", Q);  // 输出: 0

    inst2.val = true;
    Q = F_TRIG(&inst2);
    printf("Q1: %d\n", Q);  // 输出: 0

    inst1.val = false;
    Q = F_TRIG(&inst1);
    printf("Q: %d\n", Q);  // 输出: 1

    inst2.val = false;
    Q = F_TRIG(&inst2);
    printf("Q1: %d\n", Q);  // 输出: 1

    inst1.val = false;
    Q = F_TRIG(&inst1);
    printf("Q: %d\n", Q);  // 输出: 0

    inst2.val = false;
    Q = F_TRIG(&inst2);
    printf("Q1: %d\n", Q);  // 输出: 0
    return 0;
}